package archer.framework.core.lang.net;

import archer.framework.utils.ValidateUtils;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;

/**
 * ip黑/白名单
 *
 * @author kent
 * @date 16/7/6.
 */
public class IpList {

    // ip规则分隔符
    private static final String separator = ",";

    private List<IpRange> ipRanges;

    /**
     * **********************************************************
     * ddd.ddd.ddd.ddd - single IP address
     * ddd.ddd.ddd.* - class C range
     * ddd.ddd.* - class B range
     * ddd.* - class A range
     * ddd.ddd.ddd.ddd - ccc.ccc.ccc.ccc - specific range
     * **********************************************************
     * 以上多条规则以逗号分隔,如: 192.168.1.*,192.168.2.100-192.168.2.105,192.168.3.150
     *
     * @param pattern
     * @return
     */
    public static IpList create(String pattern) {

        return new IpList(parseRanges(pattern));
    }

    /**
     * 判断是否在名单中
     *
     * @param ip 如: 192.168.1.1
     * @return
     */
    public boolean contains(String ip) {

        if (ValidateUtils.isEmpty(ip)) {
            return false;
        }

        InetAddress clientIp;
        try {
            clientIp = InetAddress.getByName(ip);
        } catch (UnknownHostException e) {
            return false;
        }
        for (IpRange ipRange : ipRanges) {
            if (ipRange.isInRange(clientIp)) {
                return true;
            }
        }

        return false;
    }


    /**
     * construction
     *
     * @param ipRanges
     */
    private IpList(List<IpRange> ipRanges) {

        this.ipRanges = ipRanges;
    }


    //------------------------------------ private ----------------------------------------
    private static List<IpRange> parseRanges(String pattern) {

        List<IpRange> result = new ArrayList<>();
        if (ValidateUtils.isEmpty(pattern)) {
            return result;
        }

        String[] stringIpRanges = pattern.trim().split(separator);
        for (String range : stringIpRanges) {
            result.add(IpRange.parse(range));
        }

        return result;
    }

}
